<template>
  <div class="partcle">
    <canvas ref="showNode" @mousedown.left="createBall" />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { random, baseDistance } from '@/utils/index'
import globalStore from '@/store/global-store'

const localGlobal = globalStore()
const showNode = ref<HTMLCanvasElement>()
const showCtx = ref<CanvasRenderingContext2D>()

// 小于此距离, 创建连线
const toLine = 150

// 球, 大小
const ballSize = 5

let isDisableFlag: number | null = null

const ballArr = <Ball[]>[]

class Ball {

  x: number
  y: number
  xs: number
  ys: number
  color: string
  index?: number

  constructor(x: number, y: number) {
    this.x = x
    this.y = y
    this.xs = randomDirection()
    this.ys = randomDirection()
    this.color = `rgba(${random(0, 255)},${random(0, 255)},${random(0, 255)},`
  }

  updateDraw() {
    if (!showCtx.value) { return }

    showCtx.value.beginPath()

    showCtx.value.fillStyle = `${this.color}1)`
    showCtx.value.arc(this.x, this.y, ballSize, 0, 2 * Math.PI)
    showCtx.value.fill()


    if (this.x >= showNode.value!.width || this.x < 0) { this.xs *= -1 }
    if (this.y >= showNode.value!.height || this.y < 0) { this.ys *= -1 }

    this.x += this.xs
    this.y += this.ys
  }
}

/** 随机方向 */
const randomDirection = ():number => (Math.random() > 0.5 ? 1 : -1) * random(1, 3)

/** 创建小球 */
const drawUpBall = (size: number) => {
  for (let i = 0; i < size; i++) {
    ballArr.push(new Ball( random(0, showNode.value!.width), random(0, showNode.value!.height) ))
  }
}

/** 点击画布, 添加一个球 */
const createBall = ({ offsetX, offsetY }: {offsetX: number, offsetY: number}) => {
  ballArr.push(new Ball( offsetX, offsetY ))
}

/** 绘制画面 */
const loopDraw = () => {
  if (!showCtx.value) { return }

  showCtx.value.fillStyle = '#000'
  showCtx.value.fillRect(0, 0, showNode.value!.width, showNode.value!.height)

  for (let first = 0; first < ballArr.length - 1; first++) {
    for (let second = first + 1; second < ballArr.length; second++) {
      const distance = baseDistance(ballArr[first].x, ballArr[first].y, ballArr[second].x, ballArr[second].y)

      if (distance < toLine) {

        showCtx.value.strokeStyle = ballArr[first].color + `${(toLine - distance) / toLine})`
        showCtx.value.moveTo(ballArr[first].x, ballArr[first].y)
        showCtx.value.lineWidth = 3
        showCtx.value.lineTo(ballArr[second].x, ballArr[second].y)
        showCtx.value.stroke()
      }
    }

    ballArr[first].updateDraw()
  }

  ballArr[ballArr.length - 1].updateDraw()

  isDisableFlag = requestAnimationFrame(loopDraw)

}

watch(
  () => [localGlobal.CURRENT_SIZE_WIDTH, localGlobal.CURRENT_SIZE_HEIGHT],
  nd => {
    if (showNode.value) {
      showNode.value.width = nd[0]
      showNode.value.height = nd[1]
    }
  }
)

onMounted(() => {
  const { clientWidth, clientHeight } = <HTMLElement>document.querySelector('.partcle')

  if (!showNode.value) { return }
  showNode.value.width = showNode.value.width = clientWidth
  showNode.value.height = showNode.value.height = clientHeight - 10

  showCtx.value = <CanvasRenderingContext2D>showNode.value.getContext('2d')

  drawUpBall(30)

  loopDraw()

})

onBeforeUnmount(() => {
  if (isDisableFlag) {
    cancelAnimationFrame(isDisableFlag)
  }
})
</script>

<style lang="scss">
canvas {
  border: 1px dashed;
}
</style>